home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / TouchMe 1.2□ / touchMe 1.2 Folder / touchMe source codes / CW11 PP source / source / Common Lib / UStandardFiles.cp < prev    next >
Encoding:
Text File  |  1997-04-25  |  9.3 KB  |  304 lines  |  [TEXT/CWIE]

  1. // ==================================================
  2. //    UStandardFiles.cp
  3. //    Copyright (C) 1994-1997 Mizutori Tetsuya
  4. //    March 5, 1997
  5. // ==================================================
  6. //    All documents are pretty-printed in 10-point Geneva font.
  7.  
  8. #include <Files.h>
  9. #include <Processes.h>
  10. #include <Types.h>
  11. #include <LowMem.h>
  12.  
  13. #include "UStandardFiles.h"
  14. #include <UEnvironment.h>
  15.  
  16.  
  17. // ==================================================
  18. //    Select file or directory
  19. // ==================================================
  20. // This code for StandardGetFileOrDirectory() is greatly due to
  21. // Metrowerks CodeWarrior PowerPlant.
  22.  
  23. // Local Constants
  24.  
  25. const ResIDT        DLOG_SelectFile            = 600;
  26. const short            item_SelectThisButton        = 10;
  27. const unsigned char    mask_IsFolder            = 0x10;
  28. const char            replaceBy_thisName        = '^';
  29.  
  30.  
  31. // static Class variables
  32. Str63    UStandardFiles::sCurrentName;
  33. Str255    UStandardFiles::sSavedString;
  34. Boolean    UStandardFiles::sCustomSelection;
  35.  
  36.  
  37. // ==================================================
  38. //        • Constructors
  39. // ==================================================
  40.  
  41. // --------------------------------------------------
  42. //        • UStandardFiles()
  43. // --------------------------------------------------
  44.  
  45. UStandardFiles::UStandardFiles()
  46. {
  47. }
  48.  
  49.  
  50. // --------------------------------------------------
  51. //        • ~UStandardFiles()
  52. // --------------------------------------------------
  53.  
  54. UStandardFiles::~UStandardFiles()
  55. {
  56. }
  57.  
  58.  
  59. // --------------------------------------------------
  60. //        • StandardGetFileOrDirectory
  61. // --------------------------------------------------
  62. //    Prompts the user to select a plain file or directory using a modified
  63. //    version of the Standard Get File dialog box.
  64. //    An extra "Select Item" button is added.
  65. //
  66. //    Returns true if the user selected a plain file or directory, in which case the
  67. //    StandardFileReply will contain info about the selected item.
  68. //    ioReply->sfGood        {true if selected a plain file or directory}
  69. //    ioReply->sfFile        {file spec for the selected file, folder, or volume}
  70. //    ioReply->sfType        {its file type for a plain file; 'fold' for folder or 'disk' for volume}
  71. //    ioReply->sfIsFolder    {true if the selected item is a folder or volume}
  72. //    ioReply->sfIsVolume    {true if the selected item is a volume}
  73.  
  74. //    Returns false if the user cancelled the action.
  75. //    ioReply->sfGood        {false if the user cancelled the action}
  76.  
  77. Boolean
  78. UStandardFiles::StandardGetFileOrDirectory(
  79.     FileFilterUPP        inFileFilter,    // This file filter function is ignored.
  80.     short                inNumTypes,
  81.     ConstSFTypeListPtr    inTypeList,
  82.     StandardFileReply *    ioReply )
  83. {
  84. #pragma unused ( inFileFilter )
  85.  
  86.     sCustomSelection = false;
  87. //    SFTypeList        theTypeList;
  88.     Point            where = {-1, -1};
  89.  
  90.     // Allocate Routine Descriptors
  91.     FileFilterYDUPP    fileFilter = NewFileFilterYDProc( FileFilter_SelectFile );
  92.     DlgHookYDUPP    dlgHook = NewDlgHookYDProc( DialogHook_SelectFile );
  93.  
  94.     // Display "SelectFile" Dialog
  95. //    ::CustomGetFile( fileFilter, -1, theTypeList, ioReply, DLOG_SelectFile,
  96.     ::CustomGetFile( fileFilter, inNumTypes, inTypeList, ioReply, DLOG_SelectFile,
  97.                     where, dlgHook, NULL, NULL, NULL, ioReply );
  98.  
  99.     // Free Routine Descriptors
  100.     DisposeRoutineDescriptor( fileFilter );
  101.     DisposeRoutineDescriptor( dlgHook );
  102.  
  103.     ioReply->sfGood = ( ioReply->sfGood || sCustomSelection );
  104.  
  105.     return ( ioReply->sfGood );
  106. }
  107.  
  108.  
  109. // --------------------------------------------------
  110. //        • FileFilter_SelectFile
  111. // --------------------------------------------------
  112. //    Standard File filter function
  113.  
  114. pascal Boolean
  115. UStandardFiles::FileFilter_SelectFile(
  116.     CInfoPBPtr    inPB,
  117.     void *         inDataPtr )
  118. {
  119. #pragma unused ( inPB, inDataPtr )
  120.  
  121. //    OSType    theType = (inPB->hFileInfo).ioFlFndrInfo.fdType;
  122.  
  123.     // Screens out everything except directories (folders and volumes)
  124.     // If the file is not a folder, then returns true.
  125. //    return ( (inPB->dirInfo.ioFlAttrib & mask_IsFolder) == 0 );
  126.  
  127.     // This filter passes through any ones.
  128.     return false;
  129. }
  130.  
  131.  
  132. // --------------------------------------------------
  133. //        • DialogHook_SelectFile
  134. // --------------------------------------------------
  135. //    Standard File dialog hook
  136. //        Handles a "Select File" button in the custom standard get file dialog box.
  137. //
  138. //    The item number of the "Select File" button is item_SelectThisButton.
  139.  
  140. pascal short
  141. UStandardFiles::DialogHook_SelectFile(
  142.     short            inItem,
  143.     DialogPtr        inDialog,
  144.     void *        ioDataPtr )        // Ptr to StandardFileReply
  145. {
  146.     // This Hook is only for the main  dialog box (not a sub dialog)
  147.     if  (::GetWRefCon(inDialog) != sfMainDialogRefCon ) {
  148.         return inItem;
  149.     }
  150.  
  151.     short            itemHit = inItem;
  152.     Str255        itemName;
  153.  
  154.     // Directory Info Parameter Block
  155.     CInfoPBRec    thePB;
  156.     thePB.dirInfo.ioCompletion    = NULL;
  157.     thePB.dirInfo.ioNamePtr    = itemName;
  158.     thePB.dirInfo.ioFDirIndex    = -1;
  159.  
  160.     // Get Handle to "Select File" button
  161.     short        buttonType;
  162.     Handle    buttonH;
  163.     Rect        buttonRect;
  164.     ::GetDialogItem( inDialog, item_SelectThisButton, &buttonType, &buttonH, &buttonRect );
  165.  
  166.     if ( inItem == sfHookFirstCall ) {
  167.  
  168.         // First call, save original button name
  169.         ::GetControlTitle( (ControlHandle) buttonH, sSavedString );
  170.  
  171.         // On first call, nothing is selected. Get name of current directory
  172.         thePB.dirInfo.ioVRefNum    = -LMGetSFSaveDisk();
  173.         thePB.dirInfo.ioDrDirID    = LMGetCurDirStore();
  174.         ::PBGetCatInfoSync( &thePB );
  175.         SetSelectButtonTitle( (ControlHandle) buttonH, buttonRect, itemName );
  176.  
  177.     } else {
  178.  
  179.         StandardFileReply *    replyP = (StandardFileReply *) ioDataPtr;
  180.  
  181.         if ( replyP->sfIsFolder || replyP->sfIsVolume ) {
  182.  
  183.             // Selected file type is a folder 'fold'.
  184.             replyP->sfType = 'fold';
  185.             if ( replyP->sfIsVolume ) replyP->sfType = 'disk';
  186.             // Folder or Volume is selected. Copy its name
  187.             ::BlockMoveData( replyP->sfFile.name, itemName, StrLength(replyP->sfFile.name) + 1 );
  188.  
  189.         } else if ( replyP->sfFile.name[0] != 0 ) {
  190.  
  191.             // Selected file type is its file type. (do nothing, here)
  192.             // replyP->sfType = replyP->sfType;
  193.             // A plain file is selected. Copy its name
  194.             ::BlockMoveData( replyP->sfFile.name, itemName, StrLength(replyP->sfFile.name) + 1 );
  195.  
  196.         } else {
  197.  
  198.             // No file or directory selected. Find the Directory being viewed
  199.             thePB.dirInfo.ioVRefNum    = replyP->sfFile.vRefNum;
  200.             thePB.dirInfo.ioDrDirID    = replyP->sfFile.parID;
  201.             ::PBGetCatInfoSync( &thePB );
  202.  
  203.             // Since this Directory is not selected
  204.             //   some fields of the SF Reply will
  205.             //   not be filled in. We must fill in:
  206.             //        Is the Directory a Folder?
  207.             //        Is the Directory a Volume?
  208.             //        Script Code
  209.             //        FSSpec for Directory
  210.  
  211.             // Selected file type is 'fold' for a folder or volume.
  212.             replyP->sfType = 'fold';
  213.             // Directory is always a Folder
  214.             replyP->sfIsFolder = true;
  215.             // Volumes have special DirID
  216.             replyP->sfIsVolume = (thePB.dirInfo.ioDrDirID == fsRtDirID);
  217.             if ( replyP->sfIsVolume ) replyP->sfType = 'disk';
  218.             // Directory name uses System Script
  219.             replyP->sfScript = smSystemScript;
  220.             // Fill in FSSpec for the Directory
  221.             ::FSMakeFSSpec( thePB.dirInfo.ioVRefNum, thePB.dirInfo.ioDrParID,
  222.                             itemName, &replyP->sfFile );
  223.  
  224.         }
  225.  
  226.         // Change name of Select button to name of this selected item.
  227.         if ( IUEqualString(itemName, sCurrentName) == 1 ) {
  228.             SetSelectButtonTitle( (ControlHandle) buttonH, buttonRect, itemName );
  229.         }
  230.  
  231.         if ( inItem == item_SelectThisButton ) {
  232.             // User clicked our "Select Directory" button.
  233.             // Must fake a "Cancel" button click to dismiss dialog box.
  234.             itemHit = sfItemCancelButton;
  235.             // Set global flag so we know the user selected a directory
  236.             // (to distinguish this from a "real" cancel)
  237.             sCustomSelection = true;
  238.         }
  239.     }
  240.  
  241.     return itemHit;
  242. }
  243.  
  244.  
  245. // --------------------------------------------------
  246. //        • SetSelectButtonTitle
  247. // --------------------------------------------------
  248. //    Sets the Title of the Button for selecting a plain file or Directory
  249. //
  250. //    Before using this function, initialize sSavedString to the text for
  251. //    the Button title, using the carat (^) character as a place holder
  252. //    for the directory name. Normally, you'll make this the Button title
  253. //    in your custom dialog box.
  254. //
  255. //    On entry, ioSelectName is the name of the file or directory
  256. //    On exit, ioSelectName may be truncated to fit in the Button
  257. //
  258. //    Sets sCurrentName to entry value of ioSelectName
  259.  
  260. void
  261. UStandardFiles::SetSelectButtonTitle(
  262.     ControlHandle    inButtonH,
  263.     const Rect &    inButtonRect,
  264.     Str63        ioSelectName )
  265. {
  266.     // Save directory name
  267.     ::BlockMoveData( ioSelectName, sCurrentName, StrLength(ioSelectName)+1 );
  268.  
  269.     // Truncate name if necessary to fit inside the Button
  270.     short        maxNameWidth = ( inButtonRect.right - inButtonRect.left) -
  271.                             ::StringWidth(sSavedString) - ::CharWidth(' ');
  272.     ::TruncString( maxNameWidth, ioSelectName, smTruncMiddle );
  273.  
  274.     // Insert (truncated) selected item name into original button title
  275.     Str255    buttonName;
  276.     short        len = StrLength( sSavedString );
  277.     // Copy original name up to (but not including) the special marker
  278.     short        i = 1;
  279.     while ( (i <= len) && (sSavedString[i] != replaceBy_thisName) ) {
  280.         buttonName[i] = sSavedString[i];
  281.         i++;
  282.     }
  283.  
  284.     // Append directory name
  285.     ::BlockMoveData( ioSelectName+1, buttonName+i, StrLength(ioSelectName) );
  286.     // Append remaining part of original name (excluding the marker)
  287.     short    j = i + StrLength(ioSelectName) - 1;
  288.     while ( ++i <= len ) {
  289.         buttonName[++j] = sSavedString[i];
  290.     }
  291.     buttonName[0] = j;
  292.  
  293.     // Finally, we've got the Button name
  294.     ::SetControlTitle( inButtonH, buttonName );
  295.     ::ValidRect( &inButtonRect );
  296. }
  297.  
  298.  
  299. // ==================================================
  300. //    Common functions
  301. // ==================================================
  302.  
  303. // end of program
  304.